#include "Adetector.h"
void GetFinalState_detector_lep(CDraw &para, AnalyseClass &analyse, AObject &object, TClonesArray *branchElectron, TClonesArray *branchMuon, MyPlots *plots, bool &Jlep, bool &Jelec, bool &Jmuon){
	// if only want lepton, donot need to recognize elec or muon
	if(!para.lep.elec.SWITCH && !para.lep.muon.SWITCH){
		para.debug.Message(4,21,"get elec and muon simutaniously");
		GetFinalState_detector_elec(para,analyse.delphes.branchElectron,plots,object.Velec, Jelec);

		GetFinalState_detector_muon(para,analyse.delphes.branchMuon,plots,object.Vmuon, Jmuon);

	}
	// if need to recognize elec or muon
	else if(para.lep.elec.SWITCH || para.lep.muon.SWITCH){
		para.debug.Message(4,21,"get elec or muon seperately");
		// Analyse elec 
		if(para.lep.elec.SWITCH){
			GetFinalState_detector_elec(para,analyse.delphes.branchElectron,plots,object.Velec, Jelec);
			if(Jelec){
				analyse.counter.getCounter("basic_elec");
			}
		}
		else{
			Jelec=true;
		}

		// Analyse muon 
		if(para.lep.muon.SWITCH){
			GetFinalState_detector_muon(para,analyse.delphes.branchMuon,plots,object.Vmuon, Jmuon);
			if(Jmuon){
				analyse.counter.getCounter("basic_muon");
			}
		}
		else{Jmuon=true;}

		if((object.Velec.size()>=para.signal.NUM_elec && Jelec)|| (object.Vmuon.size()>=para.signal.NUM_muon && Jmuon)){
			Jlep=true;
			analyse.counter.getCounter("basic_lep");
		}
		else{
			Jlep=false;
			return;
		}
	}



	for(int i=0;i<object.Velec.size();i++){
		object.Lelec.push_back(object.Velec[i]->P4());
		object.Llep.push_back(object.Velec[i]->P4());
		if(object.Velec[i]->Charge>0){
			object.Lelec_p.push_back(object.Velec[i]->P4());
			object.Llep_p.push_back(object.Velec[i]->P4());
		}
		else{
			object.Lelec_m.push_back(object.Velec[i]->P4());
			object.Llep_m.push_back(object.Velec[i]->P4());
		}
	}
	for(int i=0;i<object.Vmuon.size();i++){
		object.Lmuon.push_back(object.Vmuon[i]->P4());
		object.Llep.push_back(object.Vmuon[i]->P4());
		if(object.Vmuon[i]->Charge>0){
			object.Lmuon_p.push_back(object.Vmuon[i]->P4());
			object.Llep_p.push_back (object.Vmuon[i]->P4());
		}
		else{
			object.Lmuon_m.push_back(object.Vmuon[i]->P4());
			object.Llep_m.push_back (object.Vmuon[i]->P4());
		}
	}

	std::sort(object.Llep   .begin(),object.Llep   .end(),TLV_compare_Pt);
	std::sort(object.Llep_m .begin(),object.Llep_m .end(),TLV_compare_Pt);
	std::sort(object.Llep_p .begin(),object.Llep_p .end(),TLV_compare_Pt);
	std::sort(object.Lelec  .begin(),object.Lelec  .end(),TLV_compare_Pt);
	std::sort(object.Lelec_m.begin(),object.Lelec_m.end(),TLV_compare_Pt);
	std::sort(object.Lelec_p.begin(),object.Lelec_p.end(),TLV_compare_Pt);
	std::sort(object.Lmuon  .begin(),object.Lmuon  .end(),TLV_compare_Pt);
	std::sort(object.Lmuon_m.begin(),object.Lmuon_m.end(),TLV_compare_Pt);
	std::sort(object.Lmuon_p.begin(),object.Lmuon_p.end(),TLV_compare_Pt);

	if(para.lep.SWITCH && !para.lep.elec.SWITCH && !para.lep.muon.SWITCH && object.Llep.size()<para.signal.NUM_lep){
		Jlep=false;
		return;
	}
	{
		GetFinalState_detector_cut(para,plots,object.Llep, Jlep);
		if(Jlep){
			analyse.counter.getCounter("basic_lep");
		}
		else{
			return;
		}
	}
	if(para.lep.elec.SWITCH && object.Lelec.size()<para.signal.NUM_elec){
		Jlep=false;
		return;
	}
	if(para.lep.muon.SWITCH && object.Lmuon.size()<para.signal.NUM_muon){
		Jlep=false;
		return;
	}


    Jlep=GetFinalState_detector_make_signal_lep(para, object);
}


void GetFinalState_detector_elec(CDraw &para, TClonesArray *branchElectron, MyPlots *plots,std::vector<Electron*> &elec, bool &Jelec){
	para.debug.Message(5,22,"get elec");
	int loop1=0,loope=0,num;
	float pt,y;

	para.debug.Message(5,22,"in the elec cut function", para.lep.SWITCH,para.lep.lep.SWITCH,para.lep.elec.SWITCH,para.lep.muon.SWITCH,para.lep.tau.SWITCH);
	if (para.signal.NUM_lep==0&&para.signal.NUM_elec==0){
		Jelec=true;
		return;
	} 

	num = branchElectron->GetEntries();
	para.debug.Message(5,22,"elec num", num);
	if(para.lep.SWITCH && !para.lep.elec.SWITCH && !para.lep.muon.SWITCH){
		AFill_Plot(para,plots->fLepnum,num);
	}
	else if(para.lep.SWITCH &&  para.lep.elec.SWITCH){
		AFill_Plot(para,plots->fElecnum,num);
	}

	for(loop1=0;loop1<num;loop1++){
		Electron *elec_ptr = (Electron*) branchElectron->At(loop1);
		pt = elec_ptr->PT;
		y  = std::abs(elec_ptr->Eta);

  		if( para.lep.elec.JCUT_pt  [0] == true && ( pt  < para.lep.elec.CUT_ptd  [0] || pt  > para.lep.elec.CUT_ptu  [0] )){continue;}
  		if( para.lep.elec.JCUT_eta [0] == true && ( y   < para.lep.elec.CUT_etad [0] || y   > para.lep.elec.CUT_etau [0] )){continue;}
		elec.push_back(elec_ptr);
		loope++;
	}
	if(para.lep.SWITCH && !para.lep.elec.SWITCH && !para.lep.muon.SWITCH){
		Jelec=true;
		return;
	}
	else if(para.lep.SWITCH &&  para.lep.elec.SWITCH ){
		if(loope>=1&&loope>=para.signal.NUM_elec){
			for(loop1=1;loop1<para.lep.elec.CUT_num;loop1++){
				pt   = elec[loop1-1]->PT;
				y    = std::abs(elec[loop1-1]->Eta);
				if( para.lep.elec.JCUT_pt  [loop1] == true && ( pt  < para.lep.elec.CUT_ptd  [loop1] || pt > para.lep.elec.CUT_ptu  [loop1] )){
					Jelec=false;
					return;
				}
				if( para.lep.elec.JCUT_eta [loop1] == true && ( y   < para.lep.elec.CUT_etad [loop1] || y  > para.lep.elec.CUT_etau [loop1] )){
					Jelec=false;
					return;
				}
			}

			for(loop1=0;loop1<loope;loop1++){
				if(loop1<para.signal.NUM_elec){
					AFill_Plot(para,plots->fElectronPT[loop1],elec[loop1]->PT);
					AFill_Plot(para,plots->fElectronY[loop1] ,elec[loop1]->Eta);
				} 
			}
			Jelec=true;
		}
		else{
			Jelec=false;
			return;
		}
	}
	Jelec=true;
	para.debug.Message(5,22,"end get elec",Jelec);
	return;
}





void GetFinalState_detector_muon(CDraw &para, TClonesArray *branchMuon, MyPlots *plots,std::vector<Muon*> &muon, bool &Jmuon){
	para.debug.Message(5,22,"get muon");
	int loop1=0,loopm=0,num;
	float pt,y;

	para.debug.Message(5,22,"in the muon cut function");
	if (para.signal.NUM_lep==0&&para.signal.NUM_muon==0){
		Jmuon=true;
		return;
	}

	num = branchMuon->GetEntries();
	para.debug.Message(5,22,"muon num", num, para.lep.muon.JCUT_pt.size(), para.lep.muon.CUT_ptd.size(), para.lep.muon.CUT_ptu.size());
	para.debug.Message(5,22,"muon num", num, para.lep.muon.JCUT_eta.size(), para.lep.muon.CUT_etad.size(), para.lep.muon.CUT_etau.size());
	para.debug.Message(5,22,"lep num", num, para.lep.lep.JCUT_eta.size(), para.lep.lep.CUT_etad.size(), para.lep.lep.CUT_etau.size());
	if(para.lep.SWITCH && !para.lep.elec.SWITCH && !para.lep.muon.SWITCH){
		AFill_Plot(para,plots->fLepnum,num);
	}
	else if(para.lep.SWITCH &&  para.lep.muon.SWITCH){
		AFill_Plot(para,plots->fMuonnum,num);
	}

	for(loop1=0;loop1<num;loop1++){
		Muon *muon_ptr = (Muon*) branchMuon->At(loop1);
		pt = muon_ptr->PT;
		y  = std::abs(muon_ptr->Eta);
		if( para.lep.muon.JCUT_pt  [0] == true && ( pt     < para.lep.muon.CUT_ptd  [0] || pt     > para.lep.muon.CUT_ptu  [0] )){para.debug.Message(5,22,"false: muon pt cut",pt);continue;}//endif
		if( para.lep.muon.JCUT_eta [0] == true && ( y      < para.lep.muon.CUT_etad [0] || y      > para.lep.muon.CUT_etau [0] )){para.debug.Message(5,22,"false: muon etacut", y);continue;}//endif
		muon.push_back(muon_ptr);
		loopm++;
	}//endfor jet_Cindex

	para.debug.Message(5,22,"find muon num satisfy cuts", loopm);
	para.debug.Message(5,22,"open lep or muon channel", para.lep.SWITCH, para.lep.elec.SWITCH, para.lep.muon.SWITCH);


	if(para.lep.SWITCH && !para.lep.elec.SWITCH && !para.lep.muon.SWITCH){
		Jmuon=true;
		return;
	}
	else if(para.lep.SWITCH &&  para.lep.muon.SWITCH){
		if(loopm>=1&& loopm>=para.signal.NUM_muon){
			for(loop1=1;loop1<para.lep.muon.CUT_num;loop1++){
				pt   = muon[loop1-1]->PT;
				y    = std::abs(muon[loop1-1]->Eta);
				if( para.lep.muon.JCUT_pt  [loop1] == true && ( pt     < para.lep.muon.CUT_ptd  [loop1] || pt     > para.lep.muon.CUT_ptu  [loop1] )){
					para.debug.Message(5,22,"false: muon pt cut",loop1,pt);
					Jmuon=false;
					return;
				}//endif
				if( para.lep.muon.JCUT_eta [loop1] == true && ( y      < para.lep.muon.CUT_etad [loop1] || y      > para.lep.muon.CUT_etau [loop1] )){
					para.debug.Message(5,22,"false: muon etacut",loop1, y);
					Jmuon=false;
					return;
				}//endif
			}
			for(loop1=0;loop1<loopm;loop1++){
				if(loop1<para.signal.NUM_muon){
					AFill_Plot(para,plots->fMuonPT[loop1],muon[loop1]->PT);
					AFill_Plot(para,plots->fMuonY[loop1] ,muon[loop1]->Eta);
				} 
			}
			Jmuon=true;
			return;
		}
		else{
			para.debug.Message(5,22,"false: muon num cut",loopm);
			Jmuon=false;
			return;
		}
	}
	para.debug.Message(5,22,"finish muon detector");
	Jmuon=true;
	para.debug.Message(5,22,"end get muon",Jmuon);
	return;
}




void GetFinalState_detector_cut(CDraw &para, MyPlots *plots,std::vector<TLorentzVector> &lep, bool &Jlep){
		if(lep.size()>=1){
			for(int loop1=1;loop1<para.lep.lep.CUT_num;loop1++){
				para.debug.Message(4,21,"in the cut loop, loopnum", loop1);
				float pt   = lep[loop1-1].Pt();
				float y    = std::abs(lep[loop1-1].Eta());
				if( para.lep.lep.JCUT_pt  [loop1] == true && ( pt     < para.lep.lep.CUT_ptd  [loop1] || pt     > para.lep.lep.CUT_ptu  [loop1] )){
					para.debug.Message(4,21,"false: lep pt cut",loop1,pt);
					Jlep=false;
					return;
				}//endif
				if( para.lep.lep.JCUT_eta [loop1] == true && ( y      < para.lep.lep.CUT_etad [loop1] || y      > para.lep.lep.CUT_etau [loop1] )){
					para.debug.Message(4,21,"false: lep etacut",loop1, y);
					Jlep=false;
					return;
				}//endif
			}
			for(int loop1=0;loop1<lep.size();loop1++){
				para.debug.Message(4,21,"in the fill loop, fill plot", loop1);
				if(loop1<para.signal.NUM_lep){
					AFill_Plot(para,plots->fLepPT[loop1],lep[loop1].Pt());
					AFill_Plot(para,plots->fLepY[loop1] ,lep[loop1].Eta());
				} 
			}
			para.debug.Message(4,21,"finish loop");
			Jlep=true;
			return;
		}
		else{
			Jlep =false;
			return;
		}

}
